package cn.rengy.web.framework.datagrid.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.servlet.ModelAndView;

import cn.rengy.tool.core.GenericTokenParser;
import cn.rengy.tool.core.TokenHandler;
import cn.rengy.tool.core.util._NumberUtils;
import cn.rengy.web.framework.data.transcode.ObjectTranscoder;
import cn.rengy.web.framework.datagrid.Page;
import cn.rengy.web.framework.id.IdGenerator;
import cn.rengy.web.framework.sql.Dao;
import cn.rengy.web.framework.sql.DbService;
import cn.rengy.web.framework.sql.ParseSqlUtils;
import cn.rengy.web.framework.sql._MapSqlParameterSource;
import cn.rengy.web.framework.sysenum.SysCodeService;
@Service
public class DataGridService {
	private static Logger logger = LoggerFactory.getLogger(DataGridService.class);
	@Autowired
	private DbService dbService;
	@Autowired
	private ObjectTranscoder objectTranscoder;
	@Autowired
	private IdGenerator idGenerator;
	@Autowired
	private Dao dao;
	@Autowired
	private SysCodeService sysCodeService;
	
	public Map<String,String> sys_easyui_component(){
		Map<String,String> map=null;
		List<Map<String,Object>> list=this.dbService.queryForList("select_sys_easyui_component");
		if(list!=null) {
			map=new HashMap<String,String>(list.size());
			for(Map<String,Object> m:list) {
				map.put((String)m.get("component_name"), (String)m.get("input_default_options"));
			}
		}
		return map;
	}
	
	public ModelAndView insertView(Long grid_id){
		ModelAndView view=new ModelAndView();
		view.setViewName("/view/sys/grid/edit");
		List<Map<String,Object>> columnList=this.dbService.queryForList("select_get_sys_grid_column_insert",grid_id);
		if(columnList!=null) {
			List<List<Map<String,Object>>> rowList=new ArrayList<List<Map<String,Object>>>();
			List<Map<String,Object>> row0= new ArrayList<Map<String,Object>>();
			rowList.add(row0);
			Map<String,String> component= sys_easyui_component();
			for(Map<String,Object> column:columnList) {
				String columnType=(String)column.get("edit_column_type");
				if(StringUtils.isBlank(columnType)) {
					columnType="textbox";
				}
				String options=component.get(columnType);
				GenericTokenParser parser=new GenericTokenParser("#","#",new TokenHandler() {
					@Override
					public String handleToken(String content) {
						return (String)column.get(content);
					}
					
				});
				column.put("options", parser.parse(options));
				int size=rowList.size();
				List<Map<String,Object>> row=rowList.get(size-1);
				int rowNumber=MapUtils.getIntValue(column, "insert_row");
				int rowSize=row.size();
				if(rowSize==0) {
					row.add(column);
				}else{
					Map<String,Object> currRow=row.get(rowSize-1);
					int currRowNumber=MapUtils.getIntValue(currRow, "insert_row");
					if(rowNumber==currRowNumber) {
						row.add(column);
					}else {
						List<Map<String,Object>> nextRow= new ArrayList<Map<String,Object>>();
						nextRow.add(column);
						rowList.add(nextRow);
					}
				}
			}
			view.addObject("rowList", rowList);
		}
		return view;
	}
	/**
	 * 查询列信息v2版本
	 * @param tablename
	 * @return
	 */
	public Map<String,Object> queryGridColumnV2(Long page_id){
		Map<String,Object> result=new HashMap<String,Object>();
		//List<Map<String, Object>> listColumn=new ArrayList<Map<String, Object>>();
		Map<String,Object> param=new HashMap<String,Object>();
		param.put("page_id", page_id.toString());
		param.put("is_list_column", "yes");
		List<Map<String, Object>> columnList=this.dbService.queryForListMapParameter("select_sys_grid_column_bypageid", param);
		result.put("column", columnList);
		Map<String, List<Map<String, Object>>> comboData=null;
		if(columnList!=null){
			comboData=new HashMap<String,List<Map<String, Object>>>();
			for(Map<String, Object> columnMap:columnList){
				String column_name=(String)columnMap.get("column_name");
				String is_search_column=(String)columnMap.get("is_search_column");
				String is_list_column=(String)columnMap.get("is_list_column");
				String column_display_name=(String)columnMap.get("column_display_name");
				String is_edit_column=(String)columnMap.get("is_edit_column");
				String edit_column_type=(String)columnMap.get("edit_column_type");
				String code_key=(String)columnMap.get("code_key");
				String sql_name=(String)columnMap.get("sql_name");
				if(StringUtils.isNotBlank(sql_name)){
					List<Map<String, Object>> codeList=dbService.queryForListMapParameter(sql_name, new HashMap<String,Object>());
					comboData.put(column_name,codeList);
				}else if(StringUtils.isNotBlank(code_key)){
					List<Map<String, Object>> codeList=sysCodeService.query(code_key);
					comboData.put(column_name,codeList);
				}
			}
			result.put("combo_data", comboData);
		}
		return result;
	}
	//@Cacheable(value="gridColumnCache",key="#tablename")
	public Map<String,List<Map<String, Object>>> queryGridColumn(String tablename){
		Map<String,List<Map<String, Object>>> map=null;
		List<Map<String, Object>> columnList=this.dbService.queryForList("select_sys_grid_column", tablename);
		if(columnList!=null){
			map=new HashMap<String,List<Map<String, Object>>>();
			for(Map<String, Object> columnMap:columnList){
				String column_name=(String)columnMap.get("column_name");
				String is_search_column=(String)columnMap.get("is_search_column");
				String is_list_column=(String)columnMap.get("is_list_column");
				String column_display_name=(String)columnMap.get("column_display_name");
				String is_edit_column=(String)columnMap.get("is_edit_column");
				String edit_column_type=(String)columnMap.get("edit_column_type");
				String code_key=(String)columnMap.get("code_key");
				String sql_name=(String)columnMap.get("sql_name");
				if("combobox".equals(edit_column_type)){
					if(StringUtils.isNoneBlank(sql_name)){
						List<Map<String, Object>> codeList=dbService.queryForListMapParameter(sql_name, new HashMap<String,Object>());
						map.put(column_name,codeList);
					}else{
						List<Map<String, Object>> codeList=sysCodeService.query(code_key);
						map.put(column_name,codeList);
					}
				}else if("combotree".equals(edit_column_type)){
					List<Map<String, Object>> codeList=dbService.queryForListMapParameter(sql_name, new HashMap<String,Object>());
					map.put(column_name,codeList);
				}
			}
		}
		return map;
	}
	/**
	 * 列表查询
	 * @param sqlname
	 * @param paramMap
	 * @return
	 */
	public Map<String,Object> query(String sqlname,Map<String,Object> paramMap){
		if(paramMap==null) {
			paramMap=new HashMap<String,Object>();
		}
		// pageNumber：页码，起始值 1。 pageSize：每页显示行。
		int pageNumber=_NumberUtils.toInt(paramMap.remove("pageNumber"), 1);
		int pageSize=_NumberUtils.toInt(paramMap.remove("pageSize"), 30);
		int totalCount=_NumberUtils.toInt(paramMap.remove("totalCount"), 0);
		String order=(String)paramMap.remove("order");//pageSize
		String sort=(String)paramMap.remove("sort");//pageSize
		String paging=(String)paramMap.remove("paging");//是否分页
		Map<String,Object> data=new HashMap<String,Object>();
		if("no".equals(paging)){
			List<Map<String,Object>> rows=this.dbService.queryForListMapParameter(sqlname, paramMap);
			data.put("rows", rows);
		}else{
			String countSqlid=sqlname+"-count";
			if(totalCount==0){
				totalCount=this.dbService.querySingleColumn(countSqlid,paramMap,Long.class).intValue();
			}
			data.put("total", totalCount);
			List<Map<String,Object>> rows=null;
			if(totalCount>0) {
				Page page=new Page( pageNumber, pageSize, totalCount,order,sort,"");
				String sqlValue=dbService.getSqlByName(sqlname);
				_MapSqlParameterSource sqlParameterSource=new _MapSqlParameterSource(paramMap);
				sqlValue=ParseSqlUtils.parseSql(sqlValue,sqlParameterSource);
				StringBuilder newSql=new StringBuilder("SELECT * FROM (");
				newSql.append(sqlValue).append(") T ").append(page.getOrderSql()).append(" LIMIT ").append(page.getStartRow()).append(",").append(pageSize);
				rows=this.dao.queryNamedForList(newSql.toString(), sqlParameterSource);
				objectTranscoder.transcode(sqlname, rows);
			}
			
			data.put("rows", rows);
		}
		
		return data;
	}
	@Transactional(rollbackFor = Exception.class)
	public Map<String,Object> save(String sqlid,Map<String,Object> paramMap){
		List<Map<String,Object>> insertedRows=(List)paramMap.get("insertedRows");
		List<Map<String,Object>> updatedRows=(List)paramMap.get("updatedRows");
		List<Object> deletedRowIds=(List)paramMap.get("deletedRowIds");
		Map<String,Object> gridParam=(Map<String,Object>)paramMap.get("gridParam");
		if(insertedRows!=null){
			for(Map<String,Object> insertRow:insertedRows){
				insertRow.put("id", idGenerator.nextId());
				if(gridParam!=null) {
					insertRow.putAll(gridParam);
				}
				this.dbService.updateMapParameter(sqlid+"-insert", insertRow);
			}
		}
		if(updatedRows!=null){
			List<Map<String,Object>> list=this.dbService.queryForList("select_sqllist_likename", sqlid+"-update%");
			for(Map<String,Object> map:list){
				String sqlname=(String)map.get("sql_name");
				for(Map<String,Object> updatedRow:updatedRows){
					dbService.updateMapParameter(sqlname, updatedRow);
				}
			}
			
		}
		if(deletedRowIds!=null){
			Map<String,Object> deleteParam=new HashMap<String,Object>();
			deleteParam.put("ids", deletedRowIds);
			List<Map<String,Object>> list=this.dbService.queryForList("select_sqllist_likename", sqlid+"-delete%");
			Assert.notNull(list, "delete sql must not be null");
			for(Map<String,Object> map:list){
				String sqlname=(String)map.get("sql_name");
				this.dbService.updateMapParameter(sqlname, deleteParam);
			}
			
		}
		return null;
	}
	/**
	 * treeGrid列表保存
	 * @param sqlid
	 * @param paramMap
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public Map<String,Object> treeGridSave(String sqlid,Map<String,Object> paramMap){
		List<Map<String,Object>> insertedRows=(List)paramMap.get("insertedRows");
		List<Map<String,Object>> updatedRows=(List)paramMap.get("updatedRows");
		List<Object> deletedRowIds=(List)paramMap.get("deletedRowIds");
		if(insertedRows!=null){
			for(Map<String,Object> insertRow:insertedRows){
				int i=this.dbService.updateMapParameter(sqlid+"-insert", insertRow);
			}
		}
		if(updatedRows!=null){
			for(Map<String,Object> updatedRow:updatedRows){
				int u=dbService.updateMapParameter(sqlid+"-update", updatedRow);
				if(u==0){
					int i=this.dbService.updateMapParameter(sqlid+"-insert", updatedRow);
				}
			}
		}
		if(deletedRowIds!=null){
			Map<String,Object> deleteParam=new HashMap<String,Object>();
			deleteParam.put("ids", StringUtils.join(deletedRowIds.toArray(), ','));
			List<Map<String,Object>> list=this.dbService.queryForList("select_sqllist_likename", sqlid+"-delete%");
			Assert.notNull(list, "delete sql must not be null");
			for(Map<String,Object> map:list){
				String sqlname=(String)map.get("sql_name");
				this.dbService.updateMapParameter(sqlname, deleteParam);
			}
			
		}
		return null;
	}
	
}
